﻿/*================================================================
*   Copyright (C) 2023 baichao All rights reserved.
*
*   文件名称：common_oper.cpp
*   创 建 者：baichao
*   创建日期：2023年08月02日
*   描    述：
*
================================================================*/

#include <string>   // string
#include <iostream> // cout, cerr
#include <cassert>  // assert

#include "Include/MemDBCommonDef.h"

#include "VernoxBaseLib/RecordSerializer.h"

#include "leveldb/options.h"
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
#include "leveldb/filter_policy.h"

#pragma pack(1)

#define VMS_FIELD_NUM 5

struct vms
{
    unsigned long long timeStamp;
    int _int;
    unsigned int _uint;
    long long _ll;
    unsigned long long _ull;
};
#pragma pack()

int main()
{
    // TableSchema构建
    std::cout << "TableSchema build." << std::endl;
    TableSchema tableSchema;

    tableSchema.m_nFieldNum = VMS_FIELD_NUM;
    tableSchema.m_bJsonFieldNum = VMS_FIELD_NUM;
    tableSchema.m_timeFieldNo = 1;
    OBJECTFIELDDEF Fields[VMS_FIELD_NUM];
    for (int i = 0; i < VMS_FIELD_NUM; i++)
    {
        Fields[i].m_bFieldNo = i + 1;
        Fields[i].m_bObjectFieldNo = i + 1;
    }
    Fields[0].m_bParam = 0x0008;
    Fields[0].m_bVernoxFieldType = MF_SYS_FIELDTYPE_BIGINT;

    Fields[1].m_bParam = 0;
    Fields[1].m_bVernoxFieldType = MF_SYS_FIELDTYPE_INT;

    Fields[2].m_bParam = 0x0008;
    Fields[2].m_bVernoxFieldType = MF_SYS_FIELDTYPE_INT;

    Fields[3].m_bParam = 0;
    Fields[3].m_bVernoxFieldType = MF_SYS_FIELDTYPE_BIGINT;

    Fields[4].m_bParam = 0x0008;
    Fields[4].m_bVernoxFieldType = MF_SYS_FIELDTYPE_BIGINT;

    tableSchema.m_lpField = Fields;

    leveldb::DB *ldbptr = nullptr;
    leveldb::Options options;
    options.create_if_missing = true;
    options.filter_policy = leveldb::NewBloomFilterPolicy(10);
    options.compression = leveldb::DeltaCompression;
    options.table_schema = &tableSchema;
    const std::string db_path = "/var/tmp/baichao.db";

    leveldb::Status status = leveldb::DB::Open(options, db_path, &ldbptr);
    if (!status.ok())
    {
        std::cerr << "open level db error:" << status.ToString() << std::endl;
        return 0;
    }
    assert(ldbptr != nullptr);
    std::cout << "open level db successfully !" << std::endl;

    int totals = 200000;
    int base = 1;
    unsigned long long time_stamp_base = 1000;
    leveldb::WriteOptions putOptions;
    putOptions.sync = true;

    VARDATAARRAY varDataArray;
    varDataArray.m_nArrayNum = VMS_FIELD_NUM;
    varDataArray.m_lpVarData = new VARDATA[VMS_FIELD_NUM];
    for (int i = 0; i < totals; i++)
    {
        varDataArray.m_lpVarData[0].m_vt = MF_VARDATA_INT64;
        varDataArray.m_lpVarData[0].m_ullValue = time_stamp_base + i * 1000;

        varDataArray.m_lpVarData[1].m_vt = MF_VARDATA_INT;
        varDataArray.m_lpVarData[1].m_nValue = base + i;

        varDataArray.m_lpVarData[2].m_vt = MF_VARDATA_INT;
        varDataArray.m_lpVarData[2].m_llValue = base + i;

        varDataArray.m_lpVarData[3].m_vt = MF_VARDATA_INT64;
        varDataArray.m_lpVarData[3].m_ullValue = base + i;

        varDataArray.m_lpVarData[4].m_vt = MF_VARDATA_INT64;
        varDataArray.m_lpVarData[4].m_ullValue = base + i;

        const char *recordBuffer;
        unsigned int recordBufferLen;
        RecordSerializer recordSerializer(&tableSchema);
        recordSerializer.SerializeRecord(&varDataArray);
        recordBuffer = recordSerializer.GetRecordBuffer();
        recordBufferLen = recordSerializer.GetRecordBufferLen();

        std::string currKey = std::to_string(varDataArray.m_lpVarData[0].m_ullValue);
        const leveldb::Slice  s_key= currKey;
        const leveldb::Slice s_value(recordBuffer, recordBufferLen);
        status = ldbptr->Put(putOptions, s_key, s_value);
        if (!status.ok())
        {
            std::cerr << "put data error:" << status.ToString() << std::endl;
            return 0;
        }
    }

    std::cout << "put data successfully!" << std::endl;
  
    leveldb::ReadOptions getOptions;
    getOptions.table_schema = &tableSchema;
    std::cout << "get data start!" << std::endl;
    for (int i = 0; i < totals; i++)
    {
        
        std::string currValue;
        unsigned long long timestamp =  time_stamp_base + i * 1000;
        leveldb::Slice s_key = std::to_string(timestamp);
        status = ldbptr->Get(getOptions, s_key, &currValue);
        if (!status.ok()) {
            std::cerr << "get data error:" << status.ToString() << std::endl;
            return 0;
        }
        RecordSerializer recordSerializer(&tableSchema);
        recordSerializer.DeserializeRecord(currValue.c_str(),currValue.length());
        VARDATAARRAY* VarDataArray = recordSerializer.GetVarDataArray();
        assert(VarDataArray->m_nArrayNum == VMS_FIELD_NUM);
        assert(VarDataArray->m_lpVarData[0].m_ullValue == timestamp);
    }

    std::cout << "get data successfully!" << std::endl;

    return 0;
}
